package com.hanm.util;

import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import java.util.Iterator;
import java.util.List;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class XmlParser {

	private int ov_lastError = 0;

	private String ov_lastErrorStr;

	public static final int RET_OK = 0;

	private static final int RET_ERR_UNEXCEPTED = 1;

	private static final int RET_ERR_NOTFOUND = 2;

	public XmlParser() {
	}

	public int getLastError() {
		return ov_lastError;
	}

	public String getLastErrorStr() {
		return ov_lastErrorStr;
	}

	/**
	 * get attribute value in xml string .
	 * 
	 * @av_src xml source string
	 * @av_xpath xpath expression, For example: "/UserInfo/Profile/@ver"
	 * @av_index get the value by which index is
	 * @return attribute value, null if error
	 */
	public String getAttribute(String av_src, String av_xpath) {
		return getAttribute(av_src, av_xpath, 0, 0);
	}

	public String getAttribute(String av_src, String av_xpath, int av_index, int av_attrIndex) {
		try {
			// load xml
			Document lv_doc = DocumentHelper.parseText(av_src);
			List lv_list = lv_doc.selectNodes(av_xpath);
			Iterator lv_iter = lv_list.iterator();
			int lv_index = 0;
			if (av_index >= lv_list.size()) {
				ov_lastError = RET_ERR_NOTFOUND;
				return null;
			}
			while (lv_iter.hasNext()) {
				if (lv_index == av_index) {
					Object o = lv_iter.next();
					Element ele = (Element) o;
					Attribute lv_attr = null;
					if (av_attrIndex >= ele.attributeCount()) {
						ov_lastError = RET_ERR_NOTFOUND;
						return null;
					}
					lv_attr = ele.attribute(av_attrIndex);
					return lv_attr.getValue();
				}// if( lv_index == av_index )
				else if (lv_index < av_index) {
					lv_index++;
					lv_iter.next();
					continue;
				} else if (lv_index > av_index) {
					break;
				}
			}// while( lv_iter.hasNext() )
			ov_lastError = RET_ERR_NOTFOUND;
			return null;
		} catch (DocumentException e) {
			ov_lastErrorStr = e.getMessage();
			ov_lastError = RET_ERR_UNEXCEPTED;
			return null;
		}
	}

	public String getAttribute(String av_src, String av_xpath, int av_index, String av_attrName) {
		try {
			// load xml
			Document lv_doc = DocumentHelper.parseText(av_src);
			List lv_list = lv_doc.selectNodes(av_xpath);
			Iterator lv_iter = lv_list.iterator();
			int lv_index = 0;
			if (av_index >= lv_list.size()) {
				ov_lastError = RET_ERR_NOTFOUND;
				return null;
			}
			while (lv_iter.hasNext()) {
				if (lv_index == av_index) {
					Object o = lv_iter.next();
					Element ele = (Element) o;
					Attribute lv_attr = null;
					int lv_attrIndex = -1;
					for (int i = 0; i < ele.attributeCount(); i++) {
						lv_attr = ele.attribute(i);
						if (lv_attr.getName().equalsIgnoreCase(av_attrName)) {
							lv_attrIndex = i;
							break;
						}
					}
					if (lv_attrIndex == -1) {
						ov_lastError = RET_ERR_NOTFOUND;
						return null;
					}
					lv_attr = ele.attribute(lv_attrIndex);
					return lv_attr.getValue();
				} else if (lv_index < av_index) {
					lv_index++;
					lv_iter.next();
					continue;
				} else if (lv_index > av_index) {
					break;
				}
			}
			ov_lastError = RET_ERR_NOTFOUND;
			return null;
		} catch (DocumentException e) {
			ov_lastErrorStr = e.getMessage();
			ov_lastError = RET_ERR_UNEXCEPTED;
			return null;
		}
	}

	/**
	 * get element as xml string in src xml string .
	 * 
	 * @av_src xml source string
	 * @av_xpath xpath expression, For example: "/UserInfo/Profile"
	 * @av_index get the value by which index is
	 * @return attribute value, null if error
	 */
	public String getElementAsXML(String av_src, String av_xpath) {
		return getElementAsXML(av_src, av_xpath, 0);
	}

	public String getElementAsXML(String av_src, String av_xpath, int av_index) {
		try {
			Document lv_doc = DocumentHelper.parseText(av_src);
			List lv_list = lv_doc.selectNodes(av_xpath);
			Iterator lv_iter = lv_list.iterator();
			int lv_index = 0;
			if (av_index >= lv_list.size()) {
				ov_lastError = RET_ERR_NOTFOUND;
				return null;
			}
			while (lv_iter.hasNext()) {
				if (lv_index == av_index) {
					Element lv_elem = (Element) lv_iter.next();
					return lv_elem.asXML();
				} else if (lv_index < av_index) {
					lv_index++;
					lv_iter.next();
					continue;
				} else if (lv_index > av_index) {
					break;
				}
			}
			ov_lastError = RET_ERR_NOTFOUND;
			return null;
		} catch (DocumentException e) {
			ov_lastErrorStr = e.getMessage();
			ov_lastError = RET_ERR_UNEXCEPTED;
			return null;
		}
	}

	/**
	 * get element content string in src xml string .
	 * 
	 * @av_src xml source string
	 * @av_xpath xpath expression, For example: "/UserInfo/Profile"
	 * @av_index get the value by which index is
	 * @return attribute value, null if error
	 */
	public String getElementContent(String av_src, String av_xpath) {
		return getElementContent(av_src, av_xpath, 0);
	}

	public String[] getElementsContent(String av_src, String av_xpath) {
		String[] rs = null;
		try {
			Document lv_doc = DocumentHelper.parseText(av_src);
			List<?> lv_list = lv_doc.selectNodes(av_xpath);
			int size = lv_list.size();
			if (0 >= size) {
				ov_lastError = RET_ERR_NOTFOUND;
				return null;
			}
			rs = new String[size];
			for (int i = 0; i < size; i++) {
				rs[i] = ((Element) lv_list.get(i)).getText();
			}
			return rs;
		} catch (DocumentException e) {
			ov_lastErrorStr = e.getMessage();
			ov_lastError = RET_ERR_UNEXCEPTED;
			return null;
		}
	}

	public String getElementContent(String av_src, String av_xpath, int av_index) {
		try {
			Document lv_doc = DocumentHelper.parseText(av_src);
			List<?> lv_list = lv_doc.selectNodes(av_xpath);
			Iterator<?> lv_iter = lv_list.iterator();
			int lv_index = 0;
			if (av_index >= lv_list.size()) {
				ov_lastError = RET_ERR_NOTFOUND;
				return null;
			}
			while (lv_iter.hasNext()) {
				if (lv_index == av_index) {
					Element lv_elem = (Element) lv_iter.next();
					return lv_elem.getText();
				} else if (lv_index < av_index) {
					lv_index++;
					lv_iter.next();
					continue;
				} else if (lv_index > av_index) {
					break;
				}
			}
			ov_lastError = RET_ERR_NOTFOUND;
			return null;
		} catch (DocumentException e) {
			ov_lastErrorStr = e.getMessage();
			ov_lastError = RET_ERR_UNEXCEPTED;
			return null;
		}
	}

	/**
	 * create simple xml string .
	 * 
	 * @return xml string, null if error
	 */
	public String createXMLString(String av_rootElem, String av_rootVal, String[] av_childElemList, String[] av_childValList) {
		try {
			if (av_rootElem == null) {
				return null;
			}
			Document lv_doc = DocumentHelper.createDocument();
			Element lv_rootElem = lv_doc.addElement(av_rootElem);
			if (av_rootVal != null) {
				lv_rootElem.setText(av_rootVal);
			}
			if (av_childElemList != null) {
				int lv_index = 0;
				while (lv_index < av_childElemList.length) {
					if (av_childElemList[lv_index] != null) {
						Element lv_child = lv_rootElem.addElement(av_childElemList[lv_index]);
						if (av_childValList[lv_index] != null) {
							lv_child.setText(av_childValList[lv_index]);
						}
					}
					lv_index++;
				}
			}
			return lv_doc.asXML();
		} catch (Exception e) {
			ov_lastErrorStr = e.getMessage();
			ov_lastError = RET_ERR_UNEXCEPTED;
			return null;
		}
	}

	/**
	 * create simple xml string .
	 * 
	 * @return xml string, null if error
	 */
	public String createXMLString(String av_rootElem, String av_rootVal) {
		return createXMLString(av_rootElem, av_rootVal, null, null);
	}// public String createXMLString(String av_rootElem,String av_rootVal){

	/**
	 * load xml file.
	 * 
	 * @return xml string, null if error
	 */
	public String loadXMLFile(String av_filename) {
		try {
			SAXReader reader = new SAXReader();
			Document document = reader.read(av_filename);
			return document.asXML();
		} catch (DocumentException e) {
			ov_lastErrorStr = e.getMessage();
			ov_lastError = RET_ERR_UNEXCEPTED;
			return null;
		}
	}

	public String loadXMLString(String str) {
		try {
			ByteArrayInputStream bin = new ByteArrayInputStream(str.getBytes());
			InputStreamReader in = new InputStreamReader(bin);
			SAXReader reader = new SAXReader();
			Document document = reader.read(in);
			return document.asXML();
		} catch (DocumentException e) {
			ov_lastErrorStr = e.getMessage();
			ov_lastError = RET_ERR_UNEXCEPTED;
			return null;
		}
	}
}
